package org.example.objevent.executor;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.*;

@Slf4j
@Component
public class EventExecutor {

    @Autowired
    private EventExecutorFactory executorFactory;

    @Autowired
    private EventExecutorRejectHandler rejectHandler;

    @Autowired
    private EventExecutorExceptionHandler exceptionHandler;

    @Value("${tunnel.server.thread.executor.max:16}")
    private int maxExecutors = 16;

    @Value("${tunnel.server.thread.executor.core:3}")
    private int coreExecutors = 3;

    @Value("${tunnel.server.thread.scheduler:3}")
    private int schedulers = 3;

    private LinkedBlockingQueue<Runnable> queue = null;
    private ThreadPoolExecutor threadPoolExecutor = null;
    private ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = null;

    public ScheduledExecutorService getScheduler(){
        return scheduledThreadPoolExecutor;
    }

    public ExecutorService getExecutor(){
        return threadPoolExecutor;
    }

    @PostConstruct
    private void init(){

        queue = new LinkedBlockingQueue<>();

        scheduledThreadPoolExecutor =
                new ScheduledThreadPoolExecutor(schedulers, executorFactory, rejectHandler);

        threadPoolExecutor =
                new ThreadPoolExecutor(coreExecutors, maxExecutors, 60, TimeUnit.SECONDS, queue, executorFactory, rejectHandler);

        Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);

    }

    @PreDestroy
    private void destroy(){

        try{

            threadPoolExecutor.shutdown();
            scheduledThreadPoolExecutor.shutdown();

        }catch (Throwable e){

            log.error("", e);

        }

    }


}
